package com.zhudoo.zhilian.util.web;

import com.zhudoo.zhilian.util.IpUtil;
import com.zhudoo.zhilian.util.MapConverter;
import org.apache.catalina.connector.ClientAbortException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * 公共控制层
 *
 * @author wangnian
 */
@ControllerAdvice
@RestController
public class ExceptionController {

    private static Logger logger = LoggerFactory.getLogger(ExceptionController.class);

    /**
     * 业务的提示
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({BusinessException.class})
    public Response customBizExceptionHandler(BusinessException ex) {
        logger.info("业务提示:", ex);
        switch (ex.getCodeStr()) {
            //没有登录
            case "NOT_PHONE":
                return ResponseUtil.responseNotPhone(ex.getMessage());
            //没有实名认证
            case "NOT_CERTIFICATION":
                return ResponseUtil.responseNotCertification(ex.getMessage());
            default:
                return ResponseUtil.responseFailure(ex.getMessage());
        }
    }

    /**
     * 数据库锁提示
     *
     * @param ex
     * @return
     */
    @ExceptionHandler({DeadlockLoserDataAccessException.class})
    public Response deadlockLoserDataAccessException(DeadlockLoserDataAccessException ex) {
        logger.error("数据库锁提示:", ex);
        return ResponseUtil.responseFailure("请求过于频繁,请稍后再试");
    }

    /**
     * 请求方式不对
     *
     * @param ex
     * @param request
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Response httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException ex, HttpServletRequest request) {
        logger.warn("请求方式不对=  接口地址:{},访问ip:{},异常内容:{}", request.getRequestURI(), IpUtil.getRemoteIp(request), "请求的方式不对" + ex.toString());
        return ResponseUtil.responseFailure("请求的方式不对" + ex.toString());
    }


    /**
     * 请求的参数不全
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ServletRequestBindingException.class)
    public Response servletRequestBindingExceptionHandler(ServletRequestBindingException ex, HttpServletRequest request) {
        logger.warn("请求的参数不完整=  接口地址:{},访问ip:{},异常内容:{}", request.getRequestURI(), IpUtil.getRemoteIp(request), "请求的参数不全" + ex.toString());
        return ResponseUtil.responseFailure("请填写必填项" + ex.toString());
    }

    /**
     * 程序异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Response exceptionHandler(Exception ex, HttpServletRequest request) {
        logger.error("接口异常= 接口地址:{},接口参数:{},访问ip:{},异常内容:", request.getRequestURI(), MapConverter.requestParameterMapToHashMap(request.getParameterMap()), IpUtil.getRemoteIp(request), ex);
        return ResponseUtil.responseFailure("系统升级中,请稍后再试");
    }

    /**
     * 客户端关闭丢失异常
     *
     * @param ex
     * @return
     */
    @ExceptionHandler(ClientAbortException.class)
    public Response clientAbortException(ClientAbortException ex, HttpServletRequest request) {
        logger.warn(" 客户端关闭丢失=  接口地址:{},访问ip:{},异常内容:{}", request.getRequestURI(), IpUtil.getRemoteIp(request), " 客户端关闭丢失:" + ex.toString());
        return ResponseUtil.responseFailure("客户端关闭丢失" + ex.toString());
    }


    /**
     * 获取堆栈信息
     *
     * @param ex
     * @return
     */
    private String stackMessage(Exception ex) {
        StringBuffer strBuf = new StringBuffer(ex.getMessage() + "\n");
        StackTraceElement[] errors = ex.getStackTrace();
        for (StackTraceElement e : errors) {
            strBuf = strBuf.append(e.toString() + "\n");
        }
        return strBuf.toString();
    }
}
